home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 1
/
Atari Mega Archive - Volume 1.iso
/
tex
/
dvi
/
dvipssrc.zoo
/
repack.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-12-29
|
15KB
|
476 lines
/*
* Compressed TeX fonts in PostScript. Copyright (C) 1989
* by Radical Eye Software. All Rights Reserved.
* (Slight mods by Don Knuth in December 89.)
*/
#include "structures.h" /* The copyright notice in that file is included too! */
#ifdef DEBUG
extern integer debug_flag;
#endif /* DEBUG */
/* Given a raster that has been unpacked from PK format,
* we compress it by another scheme that is suitable for
* a PostScript-oriented unpacking. We write instructions for
* a little interpreter whose one-byte instructions have the form
* 18*opcode+parameter. The interpreter forms each row based
* on simple transformations to the previous row. */
#define MAXOUT (18)
#define CMD(n) (MAXOUT*(n))
#define ADVXCHG1 CMD(0)
#define ADVXCHG1END CMD(1)
#define CHGX CMD(2)-1
#define CHGXEND CMD(3)-1
#define ADVXLSH CMD(4)
#define ADVXLSHEND CMD(5)
#define ADVXRSH CMD(6)
#define ADVXRSHEND CMD(7)
#define ADVX CMD(8)-1
#define REPX CMD(9)-1
#define SETX CMD(10)-1
#define CLRX CMD(11)-1
#define ADVXCHG2 CMD(12)
#define ADVXCHG2END CMD(13)
#define END CMD(14)
extern char *malloc() ;
extern free() ;
extern void error() ;
extern long getlong() ;
extern long unpack() ;
static int rowlength = 0 ;
static unsigned char *specdata ;
static long tslen = 0 ;
static unsigned char *tempstore, *tsp, *tsend ;
void putlong(a, i)
register char *a ;
long i ;
{
a[0] = i >> 24 ;
a[1] = i >> 16 ;
a[2] = i >> 8 ;
a[3] = i ;
}
long getlong(a)
register unsigned char *a ;
{
return ((((((a[0] << 8L) + a[1]) << 8L) + a[2]) << 8L) + a[3]) ;
}
/* First, a routine that appends one byte to the compressed output. */
#define addtse(n) {lcm=tsp-tempstore;addts(n);} /* mark END option position */
static void addts(what)
register unsigned char what ;
{
register unsigned char *p, *q ;
if (tsp >= tsend) {
if (tempstore == NULL) {
tslen = 4096 ;
tempstore = (unsigned char *)malloc((unsigned)tslen) ;
if (tempstore == NULL)
error("! out of memory") ;
tsp = tempstore ;
} else {
tslen = 2 * tslen ;
tsp = (unsigned char *)malloc((unsigned)tslen) ;
if (tsp == NULL)
error("! out of memory") ;
for (p=tempstore, q=tsp; p<tsend; p++, q++)
*q = *p ;
free((char *)tempstore) ;
tempstore = tsp ;
tsp = q ;
}
tsend = tempstore + tslen ;
}
*tsp++ = what ;
}
/* Next, a routine that discovers how to do the compression. */
#define rsh(a,b) ( ((a)==0) ? ((b)==128) : ( ((a)==255) ? ((b)==127) :\
((b)==(((a)>>1)|((a)&128))) ))
#define lsh(a,b) ( ((a)==0) ? ((b)==1) : ( ((a)==255) ? ((b)==254) :\
((b)==((((a)<<1)&255)|((a)&1))) ))
#define DIFFERENT (1)
#define LSHPOSSIB (2)
#define RSHPOSSIB (4)
#define BLKPOSSIB (8)
#define WHTPOSSIB (16)
#define ENDROW (32)
#define NOPOSSIB(n) ((n&(LSHPOSSIB|RSHPOSSIB|BLKPOSSIB|WHTPOSSIB))==0)
#define NOSHIFT(n) ((n&(LSHPOSSIB|RSHPOSSIB))==0)
/*
* Our input bytes are packed to the 16-bit word. On output,
* they're packed to bytes. Thus, we may have to skip a byte at
* the end of each row.
*/
void dochar(from, width, height)
unsigned char *from ;
short width, height ; /* in bytes */
{
register int i ;
register unsigned char *f, *t, *d ;
register unsigned char *e ;
register int accum ;
int j, k, kk ;
int diffrow ;
int repeatcount ;
int lit, pos, cmd = 0 ;
long lcm ;
int widthc ;
widthc = width + (width & 1) ; /* halfword correction */
lcm = -1 ;
if (widthc > rowlength) {
if (rowlength)
free((char *)specdata) ;
rowlength = widthc ;
specdata = (unsigned char *)malloc((unsigned)(rowlength + 15)) ;
if (specdata == NULL)
error("! out of memory") ;
}
for (i= -15, t=specdata; i<=widthc; i++, t++)
*t = 0 ;
repeatcount = 0 ;
f = specdata + 2 ;
for (j=0; j<height; j++, f = from, from += widthc) {
diffrow = 0 ;
for (i=0, t=from, d=specdata; i<width; i++, f++, t++, d++) {
if (*f == *t) {
if (*t == 0)
*d = WHTPOSSIB ;
else if (*t == 255)
*d = BLKPOSSIB ;
else
*d = 0 ;
} else {
accum = DIFFERENT ;
if (rsh(*f, *t))
accum |= RSHPOSSIB ;
else if (lsh(*f, *t))
accum |= LSHPOSSIB ;
if (*t == 0)
accum |= WHTPOSSIB ;
else if (*t == 255)
accum |= BLKPOSSIB ;
*d = accum ;
diffrow++ ;
}
} /* end 'for i' */
*d = ENDROW ;
if (diffrow == 0) {
repeatcount++ ;
} else {
if (repeatcount) {
while (repeatcount > MAXOUT) {
addts((unsigned char)(REPX+MAXOUT)) ;
repeatcount -= MAXOUT ;
}
addts((unsigned char)(REPX+repeatcount)) ;
repeatcount = 0 ;
}
pos = 0 ;
for (i=0, d=specdata, f=t-width; i<width;) {
if ((*d & DIFFERENT) == 0) {
i++ ;
d++ ;
f++ ;
} else {
accum = 0 ;
if (pos != i)
lit = NOSHIFT(*d) ;
else /* N.B.: 'lit' does not imply literate programming here */
lit = NOPOSSIB(*d) ;
for (e=d; ;e++) {
if (NOPOSSIB(*e))
lit = 1 ;
if ((*e & DIFFERENT) == 0)
break ;
if ((*e & WHTPOSSIB) &&
(e[1] & WHTPOSSIB)) {
while (*e & WHTPOSSIB) {
e++ ;
accum++ ;
}
cmd = CLRX ;
e -= accum ;
break ;
} else if ((*e & BLKPOSSIB) &&
(e[1] & BLKPOSSIB)) {
while (*e & BLKPOSSIB) {
e++ ;
accum++ ;
}
cmd = SETX ;
e -= accum ;
break ;
}
} /* end 'for e'; d pts to first bad byte, e to next good one */
while (i - pos > MAXOUT) {
addts((unsigned char)(ADVX+MAXOUT)) ;
pos += MAXOUT ;
}
if (k = (e - d)) {
if (lit) {
if (k > 2) {
if (i > pos) {
addts((unsigned char)(ADVX + i - pos)) ;
pos = i ;
}
while (k > MAXOUT) {
addts((unsigned char)(CHGX + MAXOUT)) ;
for (kk=0; kk<MAXOUT; kk++)
addts((unsigned char)(*f++)) ;
d += MAXOUT ;
pos += MAXOUT ;
i += MAXOUT ;
k -= MAXOUT ;
}
addtse((unsigned char)(CHGX + k)) ;
pos += k ;
for (; d<e; d++, i++, f++)
addts((unsigned char)(*f)) ;
} else {
if (k == 1) {
if (i == pos+MAXOUT) {
addts((unsigned char)(ADVX + MAXOUT)) ;
pos = i ;
}
addtse((unsigned char)(ADVXCHG1 + i - pos)) ;
addts((unsigned char)(*f)) ;
i++ ;
pos = i ;
d++ ;
f++ ;
} else {
if (i == pos+MAXOUT) {
addts((unsigned char)(ADVX + MAXOUT)) ;
pos = i ;
}
addtse((un